package impl

import (
	"context"
	"github.com/sirupsen/logrus"
	"monoblog/common"
	"monoblog/common/register"
	"monoblog/config"
	"monoblog/domain/dao"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"monoblog/domain/service"
	"time"
)

func init() {
	register.RegisterInstance[service.CommentService]("CommentService", func() service.CommentService {
		return &CommentServiceImpl{
			commentRepository: dao.NewCommentRepository(),
			articleRepository: dao.NewArticleRepository(),
		} // 返回唯一实例
	})
}

type CommentServiceImpl struct {
	commentRepository *dao.CommentRepository
	articleRepository *dao.ArticleRepository
}

func (s *CommentServiceImpl) Add(ctx context.Context, form dto.CommentReqForm) (string, error) {
	if form.ReplyCommentId == form.RootCommentId {
		// 回复的是根评论时，将回复人置为空（为了前端不展示）
		form.ReplyToUser = ""
	}

	// 创建评论对象
	comment := &model.Comment{
		BlogId:      form.BlogId,
		Content:     form.Content,
		RootId:      form.RootCommentId,
		ReplyId:     form.ReplyCommentId,
		ReplyToUser: form.ReplyToUser,

		UserId:    form.LoginUser.UID,
		Nickname:  form.LoginUser.Name,
		AvatarUrl: form.LoginUser.Avatar,

		Status:     model.COMMENT_OPENED.Value(),
		CreateTime: time.Now(),
	}

	//保存评论
	err := s.commentRepository.Add(comment)
	if err != nil {
		logrus.Errorf("[aid: %s] Add comment failed: %v", ctx.Value("aid"), err.Error())
		return "", err
	}

	go func() { //评论量+1
		err0 := s.articleRepository.UpdateBlogCommentCount(comment.BlogId, 1)
		if err0 != nil {
			logrus.Errorf("[aid: %s] UpdateBlogCommentCount 时出错. err = %v", ctx.Value("aid"), err0.Error())
		}
		// 将文章id加入等待更新队列
		config.GetRedisClient().SAdd(context.Background(), common.REDIS_KEY_WAIT_FOR_UPDATE_BLOG, comment.BlogId)

	}()

	//通知文章作者或被回复的用户，有新的评论
	go service.GetMomentPublishService().PublishWithComment(ctx, comment.UserId, comment.ID)

	logrus.Infof("[aid: %s] Add comment success: %v", ctx.Value("aid"), comment.ID)
	return comment.ID, nil
}

func (s *CommentServiceImpl) StatusOpen(ctx context.Context, id string) error {
	err := s.commentRepository.UpdateStatus(id, model.COMMENT_OPENED)
	if err != nil {
		logrus.Errorf("[aid: %s] comment open failed: %v", ctx.Value("aid"), err.Error())
		return err
	}
	return nil
}

func (s *CommentServiceImpl) StatusClose(ctx context.Context, id string) error {
	err := s.commentRepository.UpdateStatus(id, model.COMMENT_CLOSED)
	if err != nil {
		logrus.Errorf("[aid: %s] comment close failed: %v", ctx.Value("aid"), err.Error())
		return err
	}
	return nil
}

func (s *CommentServiceImpl) FindList(ctx context.Context) ([]*model.Comment, error) {
	categories, _, err := s.commentRepository.FindList(dto.CommentQuery{})
	return categories, err
}

// SubCommentsByRootId 获取根评论下的所有子评论
func (s *CommentServiceImpl) SubCommentsByRootId(ctx context.Context, rootId string) ([]*model.Comment, error) {
	subComments, err := s.commentRepository.FindSubListByRootId(rootId)
	if err != nil {
		logrus.Errorf("[aid: %s] FindSubListByRootId failed: %v", ctx.Value("aid"), err.Error())
		return nil, err
	}
	return subComments, nil
}

func (s *CommentServiceImpl) CommentsByBlogID(ctx context.Context, blogId string) ([]*model.Comment, error) {
	// 获取根评论
	rootComments, i, err := s.commentRepository.FindRootListByBlogId(blogId)
	if err != nil {
		logrus.Errorf("[aid: %s] FindRootListByBlogId failed: %v", ctx.Value("aid"), err.Error())
		return nil, err
	}
	if i == 0 {
		logrus.Infof("[aid: %s] no root comment found, blogId: %s", ctx.Value("aid"), blogId)
	}

	// 为每个根评论获取子评论list
	for _, rootComment := range rootComments {
		subComments, _ := s.commentRepository.FindSubListByRootId(rootComment.ID)
		rootComment.ChildComments = subComments
	}

	return rootComments, nil
}
